import types
#!/usr/bin/env python
# -*- coding: UTF-8 -*-

try:
	import math
	import pygame
	import sys
	from math import ceil
	from pygame.event import Event
	from pygame.locals import *
	from utils import *
except ImportError, err:
	print err
	sys.exit(2)

'''
Animateable "Interface"
A sprite that inherits this class must do the following:

1. Call Animatable.__init__(self) on its own __init__()
2. Call self.set_anim_params(distance_in_px, duration_in_frames) as
   soon as those params are known
3. Have a move() that sets self.animating to an int direction or zero
4. Have an update() that, if self.animating is true, calls self.slide()
   and then uses the new x and y values

Current directions are set to the arrow keys. Should probably become
their own constants (perhaps stored in utils.py).

Could also create Moveable.py. Or rename Animatable to Movable and
add the move() and r_move() methods right here (direction boundary
variables would have to be set).

Yikes. Pretty much every object uses x & y differently.
Major rework pending.
'''

SLIDE_DURATION = 6
ACCEL_SLIDE_DUR = 2



class Animateable(object):
	"""
	Animateable objects that can move diagonally

	self.animating comprises of an x and y list within a list
	self.frames_left and self.px_remaining are also [x, y]
	x and y movement are calculated separately
	"""
	def __init__(self):
		object.__init__(self)
		self.x = 0
		self.y = 0
		self.end_event = None
		self.mod = 0
		self.animating = [None, None]
		
	def set_end_event_name(self, name):
		"""
		Sets event to be posted at end of animation
		"""
		self.end_event = Event(USEREVENT, {'name' : name})

	def set_anim_params(self, distance, duration = SLIDE_DURATION):
		"""
		Sets animation parameters
		"""
		self.px_remaining = [distance, distance]
		self.frames_left = [duration, duration]
		self.orig_dist_dur = (distance, duration)

	def is_animating(self, d = -1):
		"""
		Tests whether is animating with optional direction
		"""
		if d == -1:
			return True if self.animating != [None, None] else False
		else:
			return True if self.animating[d] else False
			


	def slide(self):
		"""
		'Slides' the object according to animation parameters
		"""

		#X
		if self.frames_left[0] == 1:
			step_x = self.px_remaining[0]
		elif self.frames_left[0] <= 0:
			step_x = 0
		else:
			step_x = int(ceil(self.px_remaining[0] / self.frames_left[0]))

		if self.animating[0] == K_RIGHT:
			self.x += step_x
			self.frames_left[0] -= 1
			self.px_remaining[0] -= step_x
		elif self.animating[0] == K_LEFT:
			self.x -= step_x
			self.frames_left[0] -= 1
			self.px_remaining[0] -= step_x

		if self.frames_left[0] <= 0:
			self.reset(0)

		#Y
		if self.frames_left[1] == 1:
			step_y = self.px_remaining[1]
		elif self.frames_left[1] <= 0:
			step_y = 0
		else:
			step_y = int(ceil(self.px_remaining[1] / self.frames_left[1]))

		if self.animating[1] == K_UP:
			self.y -= step_y
			self.frames_left[1] -= 1
			self.px_remaining[1] -= step_y
		elif self.animating[1] == K_DOWN:
			self.y += step_y
			self.frames_left[1] -= 1
			self.px_remaining[1] -= step_y

		if self.frames_left[1] <= 0:
			self.reset(1)

		self.dirty = 1

	def reset(self, d):
		"""
		Resets px_remaining, frames_left to original, and clears animating for
		d direction
		"""
		self.animating[d] = None
		self.px_remaining[d] = self.orig_dist_dur[0]

		#shift mod for accelerated scrolling
		if self.mod & KMOD_SHIFT:
			self.frames_left[d] = ACCEL_SLIDE_DUR
		else:
			self.frames_left[d] = self.orig_dist_dur[1]

		if self.end_event is not None:
			#needs extra direction value possibly?
			pygame.event.post(self.end_event)











